|
To access the contents, click the chapter and section titles.
Bug Proofing Visual Basic: A Guide to Error Handling and Prevention
(Publisher: John Wiley & Sons, Inc.)
Author(s): Rod Stephens
ISBN: 0471323519
Publication Date: 11/01/98
Part Three Development
The chapters in Part 3 deal with development at a higher level than those in Part 2. Chapters 3 through 8 discuss specific coding guidelines that reduce the number of bugs in a program, and that make bugs easier to find when they do occur.
The following chapters cover higher-level design and optimization issues. A poor design can set the stage for bugs before developers even write the first line of code. These chapters expose some of the design pitfalls that can doom a project to disaster before it starts. They also emphasize some important high-level concepts you can use to make your code more manageable.
CHAPTER 9 Design
This book does not explain the design process itself. Data flow diagrams, functional decomposition, entity-relationship diagrams, and other design techniques are beyond the scope of this book. For information on design and life cycle processes in general, you should read a book on those subjects.
This chapter explains some of the design hazards that can snare unwary developers and make a good project turn bad. The first several sections deal with high-level design issues. The rest cover more detailed guidelines for subroutine design.
Design for Uniformity, Simplicity, Elegance
At all levels of design, you should treat matters as uniformly as possible. Maximize the common attributes of the different parts of the system. The more similar they are, the easier they will be to understand. You will need less time to generate low-level designs for pieces of the system that are similar to other pieces you have worked on before. By basing one part of the system on techniques that worked successfully in another, you can code more quickly and with fewer mistakes.
Later, when you discover bugs, you can apply the things you learn fixing one bug to look for others. For instance, if all reporting routines are similar, a bug in one indicates there may be a similar bug in the others.
A single elegant design is also usually apparent to users. They need to learn fewer new concepts to master the different parts of the system. The user interface will also probably reflect the uniform design.
On the other hand, I have seen several mainframe systems that contained literally hundreds of data entry and reporting screens. Most were designed and built completely separately with very little common design. The screens were inconsistent and awkward. A user had to be an expert in each of the many screens to use them. Consequently, most of the users never made use of the vast majority of the screens. They were hard to maintain and hard to use, making them relatively expensive for the small return they gave.
Make the design uniform to reduce bugs, promote maintainability, and increase user productivity.
Avoid Creeping Featuritis
As a project progresses, developers are often tempted to add new features. An enhancement might be easy because of other code that has already been written for something else. A customer might see a prototype and decide, Gee, if they can do this, they should also be able to . . . Adding features like this is called creeping featuritis or bells and whistles disease.
Do not add these extra features. Write them down and think about adding them to a future release, but do not include them in the release in which they are proposed. If the users cannot prove a feature is absolutely necessary, leave it for later. If a feature is not in the original product specification, it is probably unnecessary and the users can probably wait for it.
The original system was not designed to support these enhancements. Adding extra features during the coding phases of the project may cause subtle changes in the project and may force other parts of the system to change to accommodate. That causes bugs. In the best case, large parts of the system may need to be redesigned. In the worst case, the development team will try to force the new features into the old design. The result is more bugs and decreased maintainability.
Last-minute features can also add confusion to the user interface. What was once an elegant program becomes cluttered with confusing menus and options that most of the users never wanted in the first place. The fact that the original design did not include the new features is apparent to the users.
Besides, you probably have enough to do already. If you are so far ahead of schedule that you think you can add extra features, think again. Wait until the project is completed and tested. Then, if you still have extra time, you can consider adding new features. Or better still, you can get a head start on the next release.
Start with Minimal Functionality
Whenever you have the choice between doing just barely what is required and doing something extra, start simple. Do not provide features you do not need. Extra features are extra places to add bugs. If you later discover that you really do need a new capability, you can add it then. If you find that you do not need the extra feature, you will have saved a lot of time that you would have wasted writing, debugging, and testing the feature.
A closely related principle is to avoid unnecessary flexibility. Extra functionality creates additional work for you. Unnecessary flexibility makes it more difficult to detect bugs, even if it creates no extra work.
For example, suppose you are considering two designs for a subroutine that displays a list of five integers in a PictureBox. The first design takes five integer parameters and simply displays them. The second design takes a ParamArray as a parameter so you can pass it any number of arguments. This version would not take much extra work to implement, and in some ways might even be simpler. It creates a much larger number of test cases, however.
The first design requires that the routine take exactly five integer arguments. The second allows the routine to take fewer or more arguments. Because ParamArrays are variant arrays, the arguments can be strings, singles, or objects. They can even be other variant arrays containing more objects. Instead of testing simple variations using five integers, you need to consider all these strange cases.
If you just need the subroutine to display five integers, make it do just that. If you later find that you also need to display seven doubles, you can enhance it then or write a new routine for that purpose.
Avoid Not Invented Here Syndrome
Most programmers like to write code, particularly fast, clever, interesting code. This gives them a bias toward building instead of purchasing a product off the shelf. Building is almost always a mistake. Programming, debugging, and later maintaining even the simplest tools is very expensive. You will save time and money in the long run if you purchase tools already built by someone else.
Often a prepackaged tool does not provide the exact functionality you want. For example, a graphing control may not provide exactly the kind of three-dimensional plot you have in mind. Before you decide to build your own ActiveX graphing control, ask yourself if you really need that one kind of plot. Is it worth spending months of time programming, testing, and debugging the control? Is it worth adding another potential source of bugs to the project and increasing the projects chance of failure? Probably not.
The same principle applies to code you can obtain from another part of your company. If another group has already done the work for you, use what they have. Do not modify it unless absolutely necessary. Once you make changes, you take on the burden of writing, testing, and debugging your changes.
Avoid the Bleeding Edge
Most programmers like to work with cutting-edge tools and techniques. Unfortunately the cutting edge is very close to the bleeding edge. New tools contain bugs. That may be fine if you are producing an experimental proof-of-concept application that aims to test available technology. It can be disastrous in a project that must produce a usable product in a reasonable amount of time.
|